package com.lgywin.generate.ExeOutput;

import com.lgywin.generate.ExeOutput.ExeNeedEntity.*;
import com.lgywin.generate.comm.ExcelUtils;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class Exe_Output {
    private static String RetCodeFtlPath = "generate/data/Tool/ftl/RetCode.ftl";
    private static String NetCodeFtlPath = "generate/data/Tool/ftl/NetCode.ftl";

    private static String RetCodeCSharpFtlPath = "generate/data/Tool/ftl/RetCodeCSharp.ftl";
    private static String NetCodeCSharpFtlPath = "generate/data/Tool/ftl/NetCodeCSharp.ftl";
    private static String generateCSharpPath = "generate/data/Generate/output_proto/output_csharp/";
    private static String TableFtlPath = "generate/data/Tool/ftl/GenerateTable.ftl";
    private static String EntityFtlPath = "generate/data/Tool/ftl/GenerateEntity.ftl";
    private static String EntityExtFtlPath = "generate/data/Tool/ftl/GenerateEntityExt.ftl";
    private static String EntityQueryFtlPath = "generate/data/Tool/ftl/GenerateEntityQuery.ftl";
    private static String EntityQueryExtFtlPath = "generate/data/Tool/ftl/GenerateEntityQueryExt.ftl";
    private static String DaoFtlPath = "generate/data/Tool/ftl/GenerateDao.ftl";
    private static String DaoExtFtlPath = "generate/data/Tool/ftl/GenerateDaoExt.ftl";
    private static String MapperFtlPath = "generate/data/Tool/ftl/GenerateMapper.ftl";
    private static String MapperExtFtlPath = "generate/data/Tool/ftl/GenerateMapperExt.ftl";

    private static String ProtobufFtlPath = "/generate/data/Tool/ftl/GenerateProtobuf.ftl";

    private static String RetCodeXlsPath = "generate/data/Excel/Code_Excel/RetCode.xls";
    public static List<OutputRetCode> retCodeList = new ArrayList();

    private static String NetworkXlsPath = "generate/data/Excel/Network_Excel/";
    private static String EntityXlsPath = "generate/data/Excel/Entity_Excel/";

    private static String generateTablePath = "generate/data/Generate/output_local/output_table/";

    private static String generateEntityPath_runserver = "generate/data/Generate/output_local/output_local_runserver/output_entity/";
    private static String generateEntityExtPath_runserver = "generate/data/Generate/output_local/output_local_runserver/output_entity_ext/";
    private static String generateDaoPath_runserver = "generate/data/Generate/output_local/output_local_runserver/output_dao/";
    private static String generateDaoExtPath_runserver = "generate/data/Generate/output_local/output_local_runserver/output_dao_ext/";
    private static String generateMapperPath_runserver = "generate/data/Generate/output_local/output_local_runserver/output_mapper/";
    private static String generateMapperExtPath_runserver = "generate/data/Generate/output_local/output_local_runserver/output_mapper_ext/";

    private static String generateEntityPath_userserver = "generate/data/Generate/output_local/output_local_userserver/output_entity/";
    private static String generateEntityExtPath_userserver = "generate/data/Generate/output_local/output_local_userserver/output_entity_ext/";
    private static String generateDaoPath_userserver = "generate/data/Generate/output_local/output_local_userserver/output_dao/";
    private static String generateDaoExtPath_userserver = "generate/data/Generate/output_local/output_local_userserver/output_dao_ext/";
    private static String generateMapperPath_userserver = "generate/data/Generate/output_local/output_local_userserver/output_mapper/";
    private static String generateMapperExtPath_userserver = "generate/data/Generate/output_local/output_local_userserver/output_mapper_ext/";

    private static String generateProtoPath = "generate/data/Generate/output_proto/";

    private static String clearCmd = "cmd /c start C:/work/idea_workspace/gameserver/generate/src/main/java/com/lgywin/generate/ExeOutput/ExeClear.bat";
    private static String outputCmd = "cmd /c start C:/work/idea_workspace/gameserver/generate/src/main/java/com/lgywin/generate/ExeOutput/ExeOutput.bat";

    private static String PROTO = "Proto";

    private static List<OutputEntity> entityList = new ArrayList<>();

    private static Set<String> entityNameSet = new HashSet<>();

    public static Map<Integer, String> entitySeq = new HashMap<>();

    private static List<OutputProto> protoList = new ArrayList<>();

    private static Set<String> protoNameSet = new HashSet<>();

    private static Set<String> protoFieldTypeSet = new HashSet<>();

    static {
        protoFieldTypeSet.add("boolean");
        protoFieldTypeSet.add("String");
        protoFieldTypeSet.add("short");
        protoFieldTypeSet.add("int");
        protoFieldTypeSet.add("long");
        protoFieldTypeSet.add("float");
        protoFieldTypeSet.add("double");
        protoFieldTypeSet.add("byte");
        protoFieldTypeSet.add("char");
        protoFieldTypeSet.add("Date");

        protoFieldTypeSet.add("List");
        protoFieldTypeSet.add("Map");
    }

    private static Map<String, String> javaToTableTypeMap = new HashMap<>();

    static {
        javaToTableTypeMap.put("double", "double");
        javaToTableTypeMap.put("float", "float");
        javaToTableTypeMap.put("int", "int");
        javaToTableTypeMap.put("long", "bigint");
        javaToTableTypeMap.put("boolean", "bit");
        javaToTableTypeMap.put("String", "varchar(100)");
        javaToTableTypeMap.put("Date", "datetime");
    }

    private static Map<String, String> javaToMybatisTypeMap = new HashMap<>();

    static {
        javaToMybatisTypeMap.put("double", "double");
        javaToMybatisTypeMap.put("float", "float");
        javaToMybatisTypeMap.put("int", "int");
        javaToMybatisTypeMap.put("long", "long");
        javaToMybatisTypeMap.put("boolean", "boolean");
        javaToMybatisTypeMap.put("String", "string");
        javaToMybatisTypeMap.put("Date", "Date");
    }

    private static Map<String, String> javaToProtoTypeMap = new HashMap<>();

    static {
        javaToProtoTypeMap.put("double", "double");
        javaToProtoTypeMap.put("float", "float");
        javaToProtoTypeMap.put("int", "int32");
        javaToProtoTypeMap.put("long", "int64");
        javaToProtoTypeMap.put("boolean", "bool");
        javaToProtoTypeMap.put("String", "string");
        javaToProtoTypeMap.put("Date", "google.protobuf.Timestamp");
    }

    public static Map<Integer, String> protoSeq = new HashMap<>();

    public static void getRetCodeByExcel() throws IOException {
        List<List<Object>> lists = ExcelUtils.readExcelFirstSheet(RetCodeXlsPath);
        for (int i = 1; i < lists.size(); i++) {
            List<Object> line = lists.get(i);
            if (line != null && line.get(1) != null && StringUtils.isNotBlank(line.get(1).toString())) {
                //网络编号
                int id = 0;
                try {
                    id = Integer.parseInt(line.get(0).toString());
                } catch (Exception e) {
                    log.info("RetCodeFtlPath 表编号有错误=>" + line.toString());
                    e.printStackTrace();
                }
                OutputRetCode outputRetCode = new OutputRetCode();
                outputRetCode.setCode(id);

                //含义
                String ctx = line.get(1).toString();
                outputRetCode.setCtx(ctx);

                //标识
                String mark = line.get(2).toString();
                outputRetCode.setMark(mark);
                retCodeList.add(outputRetCode);
            }
        }
    }

    public static void getEntityByExcel() throws IOException {
        //实体的索引表
        List<List<Object>> lists = ExcelUtils.readExcelFirstSheet(EntityXlsPath + "index.xls");
        for (int i = 1; i < lists.size(); i++) {
            List<Object> line = lists.get(i);
            if (line != null && line.get(2) != null && StringUtils.isNotBlank(line.get(2).toString())) {
                //实体
                int id = 0;
                try {
                    id = Integer.parseInt(line.get(0).toString());
                } catch (Exception e) {
                    log.info("index.xls 表编号有错误=>" + line.toString());
                    e.printStackTrace();
                }
                String key = line.get(2).toString();
                key = StringUtils.substring(key, 0, StringUtils.indexOf(key, "."));

                List<OutputEntityField> fieldList = new ArrayList<>();
                OutputEntity outputEntity = new OutputEntity(id, key, line.get(1).toString(), fieldList);
                entityList.add(outputEntity);

                List<List<Object>> entitys = ExcelUtils.readExcelFirstSheet(EntityXlsPath + line.get(2).toString());
                //字段名
                List<Object> nameList = entitys.get(0);
                for (int j = 0; j < nameList.size(); j++) {
                    Object name = nameList.get(j);
                    if (name != null && StringUtils.isNotBlank(name.toString())) {
                        OutputEntityField outputData = new OutputEntityField(name.toString(), null, "", j == 0 ? 1 : 0);
                        outputEntity.add(outputData);
                    }
                }
                //字段类型
                List<Object> typeList = entitys.get(1);
                for (int j = 0; j < typeList.size(); j++) {
                    Object type = typeList.get(j);
                    if (type != null && StringUtils.isNotBlank(type.toString())) {
                        OutputEntityFieldType typeEntity = new OutputEntityFieldType();

                        String typeStr = type.toString();
                        typeEntity.setJavaType(typeStr);
                        outputEntity.getFieldList().get(j).setType(typeEntity);
                    } else {
                        throw new RuntimeException(EntityXlsPath + line.get(2).toString() + " 列 " + (j + 1) + " 有空类型！！！");
                    }
                }
                //字段注释
                List<Object> remarkList = entitys.get(2);
                for (int j = 0; j < remarkList.size(); j++) {
                    Object remark = remarkList.get(j);
                    if (remark != null && StringUtils.isNotBlank(remark.toString())) {
                        outputEntity.getFieldList().get(j).setRemark(remark.toString());
                    }
                }

                entityNameSet.add(key.toUpperCase());
                entitySeq.put(id, key);
            } else {
                throw new RuntimeException(EntityXlsPath + "index.xls" + " 第" + (i + 1) + "行有错误 " + line.toString());
            }
        }

        for (int i = 0; i < entityList.size(); i++) {
            OutputEntity entity = entityList.get(i);
            String entityName = entity.getName();
            List<OutputEntityField> fieldList = entity.getFieldList();

            for (int j = 0; j < fieldList.size(); j++) {
                OutputEntityField field = fieldList.get(j);

                //校验字段类型
                OutputEntityFieldType fieldType = field.getType();
                String javaType = fieldType.getJavaType();
                if (protoFieldTypeSet.contains(javaType)) {
                    fieldType.setTableType(javaToTableTypeMap.get(javaType));
                    fieldType.setMybatisType(javaToMybatisTypeMap.get(javaType));
                } else {
                    log.info(entityName + " 的字段类型不识别!");
                    throw new RuntimeException(entityName + " 的字段类型不识别!");
                }
            }
        }
/*
        for (int i = 0; i < entityList.size(); i++) {
            OutputEntity entity = entityList.get(i);
            entity.setName(entity.getName() + PROTO);
            log.info(entity.toString());
            List<OutputEntityField> fieldList = entity.getFieldList();
            for (int j = 0; j < fieldList.size(); j++) {
                OutputEntityField field = fieldList.get(j);
                log.info(field.toString());
            }
        }
*/

    }

    public static void getProtoByExcel() throws IOException {
        //Proto的索引表
        List<List<Object>> lists = ExcelUtils.readExcelFirstSheet(NetworkXlsPath + "index.xls");
        for (int i = 1; i < lists.size(); i++) {
            List<Object> line = lists.get(i);
            if (line != null && line.get(2) != null && org.springframework.util.StringUtils.hasText(line.get(2).toString())) {
                //Proto实体
                int id = 0;
                try {
                    id = Integer.parseInt(line.get(0).toString());
                } catch (Exception e) {
                    log.info("index.xls 编号有错误=>" + line.toString());
                    e.printStackTrace();
                }
                String key = line.get(2).toString();
                key = StringUtils.substring(key, 0, StringUtils.indexOf(key, "."));
                List<OutputProtoField> fieldList = new ArrayList<>();
                OutputProto outputProto = new OutputProto(id, key, line.get(1).toString(), fieldList);
                protoList.add(outputProto);

                List<List<Object>> protos = ExcelUtils.readExcelFirstSheet(NetworkXlsPath + line.get(2).toString());
                //字段名
                List<Object> nameList = protos.get(0);
                for (int j = 0; j < nameList.size(); j++) {
                    Object name = nameList.get(j);
                    if (name != null && StringUtils.isNotBlank(name.toString())) {
                        OutputProtoField outputData = new OutputProtoField(name.toString(), null, "");
                        outputProto.add(outputData);
                    }
                }
                //字段类型
                List<Object> typeList = protos.get(1);
                for (int j = 0; j < typeList.size(); j++) {
                    if (j >= outputProto.getFieldList().size()) {
                        break;
                    }
                    Object type = typeList.get(j);
                    if (type != null && StringUtils.isNotBlank(type.toString())) {
                        OutputProtoFieldType typeEntity = new OutputProtoFieldType();

                        String typeStr = type.toString();
                        typeEntity.setJavaType(typeStr);
                        outputProto.getFieldList().get(j).setType(typeEntity);
                    } else {
                        throw new RuntimeException(NetworkXlsPath + line.get(2).toString() + " 列 " + (j + 1) + " 有空类型！！！");
                    }
                }
                //字段注释
                List<Object> remarkList = protos.get(2);
                for (int j = 0; j < remarkList.size(); j++) {
                    Object remark = remarkList.get(j);
                    if (remark != null && StringUtils.isNotBlank(remark.toString())) {
                        outputProto.getFieldList().get(j).setRemark(remark.toString());
                    }
                }

                protoNameSet.add(key);
                protoSeq.put(id, key);
            } else {
                throw new RuntimeException(NetworkXlsPath + "index.xls" + " 第" + (i + 1) + "行有错误 " + line.toString());
            }
        }

        for (int i = 0; i < protoList.size(); i++) {
            OutputProto entity = protoList.get(i);
            String entityName = entity.getName();
            List<OutputProtoField> fieldList = entity.getFieldList();
            for (int j = 0; j < fieldList.size(); j++) {
                OutputProtoField field = fieldList.get(j);

                //校验字段类型
                OutputProtoFieldType fieldType = field.getType();
                String javaType = fieldType.getJavaType();
                if (!protoFieldTypeSet.contains(javaType)) {
                    if (StringUtils.startsWith(javaType, "List")) {

                        Pattern p = Pattern.compile("List\\<(.*?)\\>");
                        Matcher m = p.matcher(javaType);
                        if (m.find()) {
                            if (!protoNameSet.contains(m.group(1)) && !protoFieldTypeSet.contains(m.group(1))) {
                                throw new RuntimeException(NetworkXlsPath + entityName + ".xls " + "错误类型=>" + javaType);
                            } else {
                                fieldType.setFlag(2);
                                if (protoFieldTypeSet.contains(m.group(1))) {
                                    fieldType.setProtoType(javaToProtoTypeMap.get(m.group(1)));
                                } else {
                                    fieldType.setProtoType(m.group(1) + PROTO);
                                }
                            }
                        }

                    } else if (StringUtils.startsWith(javaType, "Map")) {
                        Pattern p = Pattern.compile("Map\\<(.*?)\\>");
                        Matcher m = p.matcher(javaType);
                        if (m.find()) {
                            String str = m.group(1);
                            str = StringUtils.substring(str, StringUtils.indexOf(str, ",") + 1);
                            if (!protoNameSet.contains(str) && !protoFieldTypeSet.contains(str)) {
                                throw new RuntimeException(NetworkXlsPath + entityName + ".xls " + "错误类型=>" + javaType);
                            } else {
                                fieldType.setFlag(3);
                                if (protoFieldTypeSet.contains(str)) {
                                    fieldType.setProtoType(javaToProtoTypeMap.get(str));
                                } else {
                                    fieldType.setProtoType(str + PROTO);
                                }
                            }
                        }

                    } else {
                        if (!protoNameSet.contains(javaType)) {
                            throw new RuntimeException(NetworkXlsPath + entityName + ".xls " + "错误类型=>" + javaType);
                        } else {
                            fieldType.setProtoType(javaType + PROTO);
                            fieldType.setFlag(1);
                        }

                    }
                } else {
                    fieldType.setProtoType(javaToProtoTypeMap.get(javaType));
                    fieldType.setFlag(0);
                }
            }
        }

        for (int i = 0; i < protoList.size(); i++) {
            OutputProto entity = protoList.get(i);
            entity.setName(entity.getName() + PROTO);
            //log.info(entity.toString());
            List<OutputProtoField> fieldList = entity.getFieldList();
            for (int j = 0; j < fieldList.size(); j++) {
                OutputProtoField field = fieldList.get(j);
                //log.info(field.toString());
            }
        }
    }

    private static void writeFtl(Template template, File file, Map root) throws IOException, TemplateException {
        Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
        template.process(root, out);
        out.flush();
        out.close();
    }

    private static void writeTable(Configuration cfg, Map root) throws IOException, TemplateException {
        Template template = cfg.getTemplate(TableFtlPath);
        File file = new File(generateTablePath + "initGameServer.sql");
        writeFtl(template, file, root);
    }

    private static void writeNetCode(Configuration cfg, Map root) throws IOException, TemplateException {
        Template template = cfg.getTemplate(NetCodeFtlPath);
        {
            root.put("serverName","runserver");
            File file = new File(generateEntityPath_runserver + "NetCode.java");
            writeFtl(template, file, root);
        }
        {
            root.put("serverName","userserver");
            File file = new File(generateEntityPath_userserver + "NetCode.java");
            writeFtl(template, file, root);
        }
        {
            Template template2 = cfg.getTemplate(NetCodeCSharpFtlPath);
            File file = new File(generateCSharpPath + "NetCode.cs");
            writeFtl(template2, file, root);
        }
    }

    private static void writeRetCode(Configuration cfg, Map root) throws IOException, TemplateException {
        Template template = cfg.getTemplate(RetCodeFtlPath);
        {
            root.put("serverName","runserver");
            File file = new File(generateEntityPath_runserver + "RetCode.java");
            writeFtl(template, file, root);
        }
        {
            root.put("serverName","userserver");
            File file = new File(generateEntityPath_userserver + "RetCode.java");
            writeFtl(template, file, root);
        }
        {
            Template template2 = cfg.getTemplate(RetCodeCSharpFtlPath);
            File file = new File(generateCSharpPath + "RetCode.cs");
            writeFtl(template2, file, root);
        }
    }

    private static void writeCode(Configuration cfg, Map root) throws IOException, TemplateException {
        for (int i = 0; i < entityList.size(); i++) {
            OutputEntity entity = entityList.get(i);
            root.put("entity", entity);
            //生成实体类
            Template template = cfg.getTemplate(EntityFtlPath);
            {
                root.put("serverName","runserver");
                File file = new File(generateEntityPath_runserver + entity.getName() + "Base.java");
                writeFtl(template, file, root);
            }
            {
                root.put("serverName","userserver");
                File file = new File(generateEntityPath_userserver + entity.getName() + "Base.java");
                writeFtl(template, file, root);
            }
            //生成实体扩展类 这些类一般是手写，实在不想写，只能在第一次生成时手工复制到项目。
            Template template2 = cfg.getTemplate(EntityExtFtlPath);
            {
                root.put("serverName","runserver");
                File file = new File(generateEntityExtPath_runserver + entity.getName() + ".java");
                writeFtl(template2, file, root);
            }
            {
                root.put("serverName","userserver");
                File file = new File(generateEntityExtPath_userserver + entity.getName() + ".java");
                writeFtl(template2, file, root);
            }
            //生成实体的翻页类
            Template template3 = cfg.getTemplate(EntityQueryFtlPath);
            {
                root.put("serverName","runserver");
                File dir = new File(generateEntityPath_runserver + "/query/");
                if (!dir.isDirectory()) {
                    dir.mkdirs();
                }
                File file = new File(generateEntityPath_runserver + "/query/" + entity.getName() + "QueryBase.java");
                writeFtl(template3, file, root);
            }
            {
                root.put("serverName","userserver");
                File dir = new File(generateEntityPath_userserver + "/query/");
                if (!dir.isDirectory()) {
                    dir.mkdirs();
                }
                File file = new File(generateEntityPath_userserver + "/query/" + entity.getName() + "QueryBase.java");
                writeFtl(template3, file, root);
            }

            //生成实体的翻页扩展类 这些类一般是手写，实在不想写，只能在第一次生成时手工复制到项目。
            Template template4 = cfg.getTemplate(EntityQueryExtFtlPath);
            {
                root.put("serverName","runserver");
                File dir = new File(generateEntityExtPath_runserver + "/query/");
                if (!dir.isDirectory()) {
                    dir.mkdirs();
                }
                File file = new File(generateEntityExtPath_runserver + "/query/" + entity.getName() + "Query.java");
                writeFtl(template4, file, root);
            }
            {
                root.put("serverName","userserver");
                File dir = new File(generateEntityExtPath_userserver + "/query/");
                if (!dir.isDirectory()) {
                    dir.mkdirs();
                }
                File file = new File(generateEntityExtPath_userserver + "/query/" + entity.getName() + "Query.java");
                writeFtl(template4, file, root);
            }
            //生成Dao类
            Template template5 = cfg.getTemplate(DaoFtlPath);
            {
                root.put("serverName","runserver");
                File file = new File(generateDaoPath_runserver + entity.getName() + "MapperBase.java");
                writeFtl(template5, file, root);
            }
            {
                root.put("serverName","userserver");
                File file = new File(generateDaoPath_userserver + entity.getName() + "MapperBase.java");
                writeFtl(template5, file, root);
            }

            //生成Dao类的扩展类 这些类一般是手写，实在不想写，只能在第一次生成时手工复制到项目。
            Template template6 = cfg.getTemplate(DaoExtFtlPath);
            {
                root.put("serverName","runserver");
                File file = new File(generateDaoExtPath_runserver + entity.getName() + "Mapper.java");
                writeFtl(template6, file, root);
            }
            {
                root.put("serverName","userserver");
                File file = new File(generateDaoExtPath_userserver + entity.getName() + "Mapper.java");
                writeFtl(template6, file, root);
            }
            //生成Mapper.xml
            Template template7 = cfg.getTemplate(MapperFtlPath);
            {
                root.put("serverName","runserver");
                File file = new File(generateMapperPath_runserver + entity.getName() + "MapperBase.xml");
                writeFtl(template7, file, root);
            }
            {
                root.put("serverName","userserver");
                File file = new File(generateMapperPath_userserver + entity.getName() + "MapperBase.xml");
                writeFtl(template7, file, root);
            }

            //生成Mapper.xml的扩展类 这些类一般是手写，实在不想写，只能在第一次生成时手工复制到项目。
            Template template8 = cfg.getTemplate(MapperExtFtlPath);
            {
                root.put("serverName","runserver");
                File file = new File(generateMapperExtPath_runserver + entity.getName() + "Mapper.xml");
                writeFtl(template8, file, root);
            }
            {
                root.put("serverName","userserver");
                File file = new File(generateMapperExtPath_userserver + entity.getName() + "Mapper.xml");
                writeFtl(template8, file, root);
            }
        }
    }

    private static void writeProto(Configuration cfg, Map root) throws IOException, TemplateException {
        Template t1 = cfg.getTemplate(ProtobufFtlPath);
        {
            root.put("serverName","runserver");
            File file = new File(generateProtoPath + "GameData.proto");
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
            t1.process(root, out);
            out.flush();
            out.close();
        }
        {
            root.put("serverName","userserver");
            File file = new File(generateProtoPath + "GameDataToUserserver.proto");
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
            t1.process(root, out);
            out.flush();
            out.close();
        }
    }

    private static void exeClearBat() {
        try {
            Runtime.getRuntime().exec(clearCmd);
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

    private static void exeOutputBat() {
        try {
            Runtime.getRuntime().exec(outputCmd);
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException, TemplateException {
        exeClearBat();

        getRetCodeByExcel();

        getEntityByExcel();

        getProtoByExcel();

        Configuration cfg = new Configuration();
        TemplateLoader templateLoader = new FileTemplateLoader(new File("C:\\work\\idea_workspace\\gameserver"));
        cfg.setTemplateLoader(templateLoader);
        Map root = new HashMap();
        root.put("entityList", entityList);
        root.put("retCodeList", retCodeList);
        root.put("protoList", protoList);

        writeTable(cfg, root);

        writeNetCode(cfg, root);

        writeRetCode(cfg, root);

        writeCode(cfg, root);

        writeProto(cfg, root);

        exeOutputBat();

    }


}
